package com.lambkit.core.processor;


import java.util.*;

import com.lambkit.core.AppContext;
import com.lambkit.core.DataContext;
import com.lambkit.core.IContext;
import com.lambkit.core.Lambkit;

/**
 * 后处理器容器
 * @param <T>
 */
public class PostProcessorContainer<T extends IContext> {
    private AppContext appContext;
    private Class<IPostProcessor> monitorPostProcessorClass;

//    public static <T> PostProcessorContainer getInstance(Class<T> monitorPostProcessorClass) {
//        PostProcessorContainer postProcessorContainer = new PostProcessorContainer();
//        postProcessorContainer.setMonitorPostProcessorClass(monitorPostProcessorClass);
//        return postProcessorContainer;
//    }

    public boolean handleBefore(T dataContext) {
        Map<String, IPostProcessor> processors = null;
        try {
            processors = Lambkit.app(appContext.getName()).getBeanFactory().getBeansMapOfType(monitorPostProcessorClass);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<IPostProcessor> list = new ArrayList<>();
        for (IPostProcessor bpp : processors.values()) {
            list.add(bpp);
        }
        if (list.size() == 0) {
            return true;//skip handle before
        }
        //sort
        Collections.sort(list,
                (Comparator<IPostProcessor>) (o1, o2)
                        -> Integer.valueOf(o1.getPriority()).compareTo(Integer.valueOf(o2.getPriority()))
        );
        //handle
        for (IPostProcessor bpp : list) {
            boolean isContinue = bpp.handleBefore(dataContext);
            if(!isContinue) {
                return false;
            }
        }
        return true;
    }

    public void handleAfter(T dataContext) {
        Map<String, IPostProcessor> processors = null;
        try {
            processors = Lambkit.app(appContext.getName()).getBeanFactory().getBeansMapOfType(monitorPostProcessorClass);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<IPostProcessor> list = new ArrayList<>();
        for (IPostProcessor bpp : processors.values()) {
            list.add(bpp);
        }
        if (list.size() == 0) {
            return;//skip handle
        }
        //sort
        Collections.sort(list,
                (Comparator<IPostProcessor>) (o1, o2)
                        -> Integer.valueOf(o2.getPriority()).compareTo(Integer.valueOf(o1.getPriority()))
        );
        //handle
        for (IPostProcessor bpp : list) {
            bpp.handleAfter(dataContext);
        }
    }

    public Class<IPostProcessor> getMonitorPostProcessorClass() {
        return monitorPostProcessorClass;
    }

    public void setMonitorPostProcessorClass(Class<IPostProcessor> monitorPostProcessorClass) {
        this.monitorPostProcessorClass = monitorPostProcessorClass;
    }
}
